#pragma once
#include <iostream>
#include <vector>
#include <semaphore.h>
#include <pthread.h>
using namespace std;

template <class T>
class RingQueue
{
    const static int deafaultcap = 5;

private:
    void P(sem_t *sem)
    {
        sem_wait(sem);
    }

    void V(sem_t *sem)
    {
        sem_post(sem);
    }

    void Lock(pthread_mutex_t* mutex)
    {
        pthread_mutex_lock(mutex);
    }

    void UnLock(pthread_mutex_t* mutex)
    {
        pthread_mutex_unlock(mutex);
    }

public:
    RingQueue(int cap = deafaultcap) : ringQueue(cap), p_step_(0), c_step_(0), cap_(cap)
    {
        sem_init(&cdate_sem_, 0, 0);
        sem_init(&pspace_sem_, 0, cap);
        pthread_mutex_init(&p_mutex_,nullptr);
        pthread_mutex_init(&c_mutex_,nullptr);
    }
    ~RingQueue()
    {
        sem_destroy(&cdate_sem_);
        sem_destroy(&pspace_sem_);
        pthread_mutex_destroy(&p_mutex_);
        pthread_mutex_destroy(&c_mutex_);

    }

    void Push(const T &in)
    {
        P(&pspace_sem_);
        Lock(&p_mutex_);
        ringQueue[p_step_] = in;
        //cout<<"在"<<p_step_<<"生产"<<in<<endl;
        int temp = p_step_ + 1;
        p_step_ = temp % cap_;
        UnLock(&p_mutex_);
        V(&cdate_sem_);
    }

    void Pop(T *out)
    {
        P(&cdate_sem_);
        Lock(&c_mutex_);
        *out = ringQueue[c_step_];
        //cout<<"在"<<c_step_<<"消费"<<*out<<endl;
        int temp = c_step_ + 1;
        c_step_ = temp% cap_;
        UnLock(&c_mutex_);
        V(&pspace_sem_);
    }

private:
    vector<T> ringQueue;
    int p_step_;
    int c_step_;
    int cap_;
    sem_t cdate_sem_;
    sem_t pspace_sem_;
    pthread_mutex_t p_mutex_;
    pthread_mutex_t c_mutex_;
};